<?php

namespace App\Core;

use Validator;
use Illuminate\Database\Eloquent\Model as BaseModel;
use App\Core\Exceptions\{ValidatorNotFoundException, ValidatorRulesNotFoundException};

class Model extends BaseModel
{
    /**
     * 较验器
     *
     * @var \Illuminate\Validation\Validator
     */
    protected $validator;

    /**
     * 较验规则
     *
     * @var array
     */
    protected $validatorRules = [];

    /**
     * 较验提示信息
     *
     * @var array
     */
    protected $validatorMessages = [];

    /**
     * 保存数据
     * 
     * @return bool
     */
    public function save(array $options = [])
    {
        if (!$this->isValid()) {
            return false;
        }

        return parent::save($options);
    }

    /**
     * 数据较验
     *
     * @return bool
     */
    public function isValid()
    {
        if (!property_exists($this, 'validatorRules')) {
            throw new ValidatorRulesNotFoundException('validator rule array did not defined in class ' . get_called_class());
        }

        $this->validator = Validator::make($this->getAttributes(), $this->getValidatorRules(), $this->validatorMessages);

        $this->validator->after(function($validator){
            $this->afterValidationHook($validator);
        });

        return $this->validator->passes();
    }

    /**
     * 获取校验错误提示信息
     *
     * @return \Illuminate\Support\MessageBag
     */
    public function getErrors()
    {
        if (!$this->validator) {
            throw new ValidatorNotFoundException('validator did not defined in class ' . get_called_class());
        }

        return $this->validator->errors();
    }

    /**
     * 获取较验规则
     *
     * @return array
     */
    protected function getValidatorRules()
    {
        return $this->replaceIdsIfExists($this->validatorRules);
    } 

    /**
     * 如果数据模型已经存在, 替换较验规则中的字符串`<id>`为当前数据模型主键
     *
     * @param  array $rules
     * @return array
     */
    protected function replaceIdsIfExists($rules)
    {
        $newRules = [];

        foreach ($rules as $key => $rule) {
            if (str_contains($rule, '<id>')) {
                $replacement = $this->exists ? $this->getAttribute($this->primaryKey) : 'NULL';
                $rule = str_replace('<id>', $replacement, $rule);
            }
            array_set($newRules, $key, $rule);
        }

        return $newRules;
    }

    /**
     * 追加较验规则
     *
     * @param  \Illuminate\Validation\Validator $validator
     * @return void
     */
    protected function afterValidationHook($validator)
    {
        // if ($this->somethingElseIsInvalid()) {
        //     $validator->errors()->add('field', 'Something is wrong with this field!');
        // }
    } 
}